# -*- coding: utf-8 -*-
import tkinter
from tkinter.scrolledtext import ScrolledText
import os
import re
import time
import threading
import ctypes
import shutil
import openpyxl
import json
import requests

# 配置xlsx文件名称
ConfigXlsx = "Config.xlsx"
# 爬取数据间隔时间10分钟，单位秒
SpiderInterval = 10 * 60
# 价格写入第几列，从1开始数
JDPriceColIndex = 8
# 京东商品URL在第几列, 从1开始数
JDUrlColIndex = 9


def get_jd_url_item(url):
    if not isinstance(url, str) or url == "":
        return None
    items = re.compile('item.jd.com/(.*?).html').findall(url)
    if len(items) > 0:
        return items[0]
    return None


def find_json_price(obj, item):
    for i in range(len(obj)):
        if item == obj[i]["id"]:
            return obj[i]["p"]
    return None


def do_spider(gui):
    gui.write_log("正在读取配置文件“" + ConfigXlsx + "”内容...")

    read_data = {}
    book = openpyxl.load_workbook(ConfigXlsx)
    sheet = book.active
    for index in range(sheet.max_row):
        url = sheet.cell(row=index + 1, column=JDUrlColIndex).value
        item = get_jd_url_item(url)
        if item:
            gui.write_log("第" + str(index + 1) + "行:" + url)
            read_data[index] = "J_" + item

    if len(read_data) == 0:
        gui.write_log("配置文件“" + ConfigXlsx + "”没有内容!")
        return

    gui.write_log("开始请求京东商城数据...")
    skuIds = ""
    for _, v in read_data.items():
        skuIds += v + ","
    response = requests.request("GET", "https://p.3.cn/prices/mgets?skuIds=" + skuIds, headers={
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4146.4 Safari/537.36'
    }, data={})
    obj = json.loads(response.text)
    gui.write_log("请求京东商城数据成功，开始写入xlsx文件...")

    if not os.path.exists("data"):
        os.mkdir("data")
    new_xlsx = "data\\" + time.strftime('%Y-%m-%d %H-%M-%S', time.localtime(time.time())) + ".xlsx"
    shutil.copyfile(ConfigXlsx, new_xlsx)
    book = openpyxl.load_workbook(new_xlsx)
    sheet = book.active

    for k, v in read_data.items():
        price = find_json_price(obj, v)
        if price:
            sheet.cell(row=k + 1, column=JDPriceColIndex).value = price
    book.save(new_xlsx)  # 保存工作簿
    gui.write_log("写入[" + new_xlsx + "]文件成功！")


def thread_spider(gui):
    while True:
        try:
            do_spider(gui)
        except Exception as e:
            gui.write_log("致命错误:" + str(e))
            gui.write_log("请联系开发人员。")
            return

        gui.write_log("已完成，等待" + str(SpiderInterval) + "秒后重新获取数据。")
        time.sleep(SpiderInterval)


class MyWindow:
    def __init__(self, w):
        self.app = w
        self.log_data_Text = ScrolledText()
        self.log_data_Text.pack(side=tkinter.BOTTOM, expand=True, fill=tkinter.BOTH)

    # 设置窗口
    def set_init_window(self):
        self.app.title("京东商品价格查询工具 v1.0")
        # 设置窗口宽高
        width = 600
        height = 400
        # 得到屏幕宽高
        sw = self.app.winfo_screenwidth()
        sh = self.app.winfo_screenheight()
        x = (sw - width) / 2
        y = (sh - height) / 2
        self.app.geometry("%dx%d+%d+%d" % (width, height, x, y))
        self.log_data_Text.insert(tkinter.END, "*** 默认10分钟获取一次数据，若想要立即获取数据，请重启本软件。***\n")
        self.log_data_Text.configure(state='disabled')

    def write_log(self, msg):
        cur_date_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
        date_time_msg = cur_date_time + " " + str(msg) + "\n"
        self.log_data_Text.configure(state='normal')
        self.log_data_Text.insert(tkinter.END, date_time_msg)
        self.log_data_Text.see(tkinter.END)
        self.log_data_Text.configure(state='disabled')


def main():
    # 隐藏控制台窗口
    console_window = ctypes.windll.kernel32.GetConsoleWindow()
    if console_window != 0:
        ctypes.windll.user32.ShowWindow(console_window, 0)
        ctypes.windll.kernel32.CloseHandle(console_window)

    # GUI窗口
    app = tkinter.Tk()
    win = MyWindow(app)
    win.set_init_window()
    app.protocol("WM_DELETE_WINDOW", app.destroy)

    # 开启线程修改
    t = threading.Thread(target=thread_spider, args=(win,))
    t.start()
    app.mainloop()

    # 强制退掉进程(不管那个线程了)
    ctypes.windll.kernel32.ExitProcess(0)


main()
